package org.example.utils

import org.apache.commons.lang3.time.FastDateFormat
import org.joda.time.format.DateTimeFormat
import org.joda.time.{DateTime, Duration}

import java.sql.Timestamp
import java.text.SimpleDateFormat
import java.util.regex.{Matcher, Pattern}
import java.util.{Calendar, Date, UUID}

object Tools {

  def rmAscII(x: String): String = {


    ""
  }

  //根据经纬度计算两点距离 单位为公里
  def getDistance(lon1: Double, lat1: Double, lon2: Double, lat2: Double): Double = {
    if (lat1 != 0 && lon1 != 0 && lat2 != 0 && lon2 != 0) {
      val R = 6378.137
      val radLat1 = lat1 * Math.PI / 180
      val radLat2 = lat2 * Math.PI / 180
      val a = radLat1 - radLat2
      val b = lon1 * Math.PI / 180 - lon2 * Math.PI / 180
      val s = 2 * Math.sin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)))
      val result = BigDecimal.decimal(s * R).setScale(3, BigDecimal.RoundingMode.HALF_UP).doubleValue() * 1000
      //println("经度1："+lon1+",纬度1："+lat1+",经度2："+lon2+",纬度2："+lat2+",距离计算结果为："+result)
      result
    } else {
      BigDecimal.decimal(0).setScale(3, BigDecimal.RoundingMode.HALF_UP).doubleValue() * 1000
    }
  }

  /**
   * 角度换算成弧度
   *
   * @param d 角度
   * @return
   */
  def rad(d: Double): Double = {
    return d * Math.PI / 180.0
  }

  /**
   * 根据经纬度计算两点间的球面距离
   *
   * @param lat1 纬度1
   * @param lng1 经度1
   * @param lat2 纬度2
   * @param lng2 经度2
   * @return
   */
  def Distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double = {
    var s = 0D
    if (null != lat1 && null != lng1 && null != lat2 && null != lng2) {
      val EARTH_RADIUS = 6371.830D
      val radLat1 = rad(lat1)
      val radLat2 = rad(lat2)
      val radLng1 = rad(lng1)
      val radLng2 = rad(lng2)
      //var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)))
      s = Math.acos(Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(radLng1 - radLng2) + Math.sin(radLat1) * Math.sin(radLat2))
      s = s * EARTH_RADIUS
      s = Math.round(s * 1000D) / 1000D
      s
    } else {
      0D
    }
  }

  /**
   * 创建UUID
   *
   * @return
   */
  def createUUID(): String = {
    UUID.randomUUID().toString.toUpperCase
  }

  def createUUID(str: String): String = {
    UUID.nameUUIDFromBytes(str.getBytes()).toString.toUpperCase()
  }

  /**
   * 创建32位的UUID
   *
   * @return
   */
  def createUUID32(): String = {
    UUID.randomUUID().toString.replace("-", "").toUpperCase
  }

  def StringToTimeStamp(time: String): Timestamp = {
    val millis = DateTime.parse(time, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).getMillis
    new Timestamp(millis)
  }

  def createUUID32(str: String): String = {
    UUID.nameUUIDFromBytes(str.getBytes()).toString.replace("-", "").toUpperCase
  }

  /**
   * 字符串转时间戳
   *
   * @param time
   * @return
   */



  def parseTimeStamp(time: String): Long = {
    try {
      val fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
      fm.parse(time).getTime/1000
    }
    catch {
      case _: Exception => 0L
    }
  }

  /**
   * 获取当前时间 yyyy-MM-dd HH:mm:ss格式
   *
   * @return
   */
  def getCurrentDate(): String = {
    //    val simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    //    simpleDate.format(new Date())
    new DateTime().toString("yyyy-MM-dd HH:mm:ss")
  }

  def getDate(date: String): String = {
    //9/1/2020 15:00:23
    //    DateTime.
    DateTime.parse(date, DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss")).toString("yyyy-MM-dd HH:mm:ss")
  }


  def getPerson(name: String): BigDecimal = {
    //val s="1.8111万人次";
    var num = BigDecimal(0)
    val s1 = name.substring(0, name.length - 2)
    //val s2="1.8111万"
    if (s1.substring(s1.length - 1, s1.length).equals("万")) {
      num = s1.substring(0, s1.length - 1).toDouble * 10000
    } else {
      num = s1.toDouble
    }
    num
  }

  def getTime(name: String): BigDecimal = {
    name match {
      case "" => BigDecimal(0)
      case _ => name.substring(0, name.length - 2).toDouble * 60
    }
  }


  /**
   * 两个时间差 yyyy-MM-dd HH:mm:ss格式
   *
   * @param a
   * @param b
   * @return 秒数
   */
  def getBetweenSecond(a: String, b: String): Long = {

    val startDate = DateTime.parse(a, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
    val endDate = DateTime.parse(b, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
    Math.abs(new Duration(startDate, endDate).getStandardSeconds)
  }

  /**
   * 判断是否是timestamp类型的数据
   *
   * @param datetime
   * @return
   */
  def patternTimestamp(datetime: String): Boolean = {
    if (datetime.isEmpty) return false
    val regex = "\\d{4}-\\d{2}-\\d{2}\\s{1}\\d{2}:\\d{2}:\\d{2}.\\d{1}"
    val pattern: Pattern = Pattern.compile(regex)
    val matcher: Matcher = pattern.matcher(datetime)
    matcher.matches()
  }

  /**
   * 获取最近时间的半整点
   *
   * @return
   */
  def getNearHalfTime(): (String, String, String, Long) = {
    // 1代表整点，2代表半小时
    var hourType = "1"
    val calendar: Calendar = Calendar.getInstance()
    val minute: Int = calendar.get(Calendar.MINUTE)
    var count = 0
    if (minute != 0 && minute != 30) {
      if (minute <= 15) {
        count = -minute
      } else if (minute > 45) {
        count = 60 - minute
      } else if (minute > 15 && minute <= 45) {
        count = 30 - minute
      }
    }
    calendar.add(Calendar.MINUTE, count)

    var hour = calendar.get(Calendar.HOUR_OF_DAY).toString // 小时
    if (hour.length == 1) {
      hour = "0" + hour
    }
    val newMinute = calendar.get(Calendar.MINUTE) // 分钟
    if (newMinute == 30) {
      hourType = "2"
    }
    val format = FastDateFormat.getInstance("yyyyMMdd")
    // yyyyMMdd格式时间
    val timekey = format.format(calendar.getTime)
    (timekey, hour, hourType, calendar.getTimeInMillis / 1000)
  }

  import java.text.DecimalFormat

  def getDataFormat(d: BigDecimal): BigDecimal = {
    val df = new DecimalFormat("0.00")
    df.format(d) toDouble
  }

  def getPlanHour(): String = {
    val date = new SimpleDateFormat("HH").parse(new DateTime().toString("HH"))
    val end_time = new DateTime(date).plusMinutes(+60).toString("HH")
    end_time
  }

  def getBeforeHour(): String = {
    val date = new SimpleDateFormat("HH").parse(new DateTime().toString("HH"))
    val end_time = new DateTime(date).plusMinutes(-60).toString("HH")
    end_time
  }

  def getHour(): String = {
    new DateTime().toString("HH")
  }

  def getTime(): String = {
    new DateTime().toString("HH:00:00")
  }

  def getPlanTime(): String = {
    val date = new SimpleDateFormat("HH:mm:ss").parse(new DateTime().toString("HH:mm:ss"))
    new DateTime(date).plusMinutes(+60).toString("HH:00:00")
  }

  def getBeforeTime(): String = {
    val date = new SimpleDateFormat("HH:mm:ss").parse(new DateTime().toString("HH:mm:ss"))
    new DateTime(date).plusMinutes(-60).toString("HH:00:00")
  }

  def getDate(): String = {
    new DateTime().toString("yyyy-MM-dd")
  }

  def beforeDate(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -1)
    ymdFormat.format(day.getTime)
  }

  def beforeFivMinuteDateTime(): String = {
    val ymdFormat = new SimpleDateFormat("HH:mm:ss")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -1)
    day.add(Calendar.MINUTE, -5)
    ymdFormat.format(day.getTime)
  }

  def planHourDateTime(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd HH:00:00")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -1)
    day.add(Calendar.HOUR, +1)
    ymdFormat.format(day.getTime)
  }

  def beforeHourDateTime(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd HH:00:00")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -1)
    day.add(Calendar.HOUR, -1)
    ymdFormat.format(day.getTime)
  }


  def beforeDateTime(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd HH:00:00")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -1)
    ymdFormat.format(day.getTime)
  }

  def planHourTime(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd HH:00:00")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.HOUR, 1)
    ymdFormat.format(day.getTime)
  }

  def beforeTwoDate(): String = {
    val ymdFormat = new SimpleDateFormat("yyyy-MM-dd")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.DATE, -2)
    ymdFormat.format(day.getTime)
  }

  //日期格式转换
  def StrToDate(dateStr: String): Date = {
    val pattern = "yyyy-MM-dd HH:mm:ss"
    val date = new SimpleDateFormat(pattern).parse(dateStr)
    //val dateTime = new DateTime(date)
    date
  }

  def StrToDateTime(dateStr: String): DateTime = {
    val pattern = "yyyy-MM-dd HH:mm:ss"
    val date = new SimpleDateFormat(pattern).parse(dateStr)
    val dateTime = new DateTime(date)
    dateTime
  }

  def getNewHour(): String = {
    var hour = Tools.getHour()
    var nextHour = Tools.getPlanHour()
    hour = hour + ":00"
    nextHour = nextHour + ":00"
    hour + "--" + nextHour
  }

  /**
   * 获取时间的整点
   *
   * @return
   */
  def getCurrTime(): String = {

    val calendar = Calendar.getInstance()
    val minute = calendar.get(Calendar.MINUTE)
    var count = 0

    if (minute > 45) {
      count = 60 - minute
    }

    calendar.add(Calendar.MINUTE, count)
    calendar.set(Calendar.MINUTE, 0)
    calendar.set(Calendar.SECOND, 0)
    val format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
    // yyyy-MM-dd HH:mm:ss格式时间
    val currTime = format.format(calendar.getTime)
    currTime

  }


  /**
   * 获取历史时间 yyyyMMddHH格式
   */
  def getHistoryTime(): (String, String, String) = {
    val calendar = Calendar.getInstance()
    val minute = calendar.get(Calendar.MINUTE)
    var count = 0

    if (minute > 45) {
      count = 60 - minute
    }

    calendar.add(Calendar.MINUTE, count)
    val format = FastDateFormat.getInstance("yyyyMMddHH")
    calendar.set(Calendar.HOUR_OF_DAY, -1)
    // 当前时间前一个小时
    val preHour = format.format(calendar.getTime)
    // 当前时间前一天
    calendar.set(Calendar.HOUR_OF_DAY, -23)
    val preDay = format.format(calendar.getTime)
    // 当前时间前一周
    calendar.set(Calendar.DAY_OF_MONTH, -6)
    val preWeek = format.format(calendar.getTime)
    (preHour, preDay, preWeek)

  }

  /**
   * 比较饱和度大小
   *
   * @param number
   * @return
   */
  def getSaturation(number: BigDecimal): BigDecimal = {
    var max = BigDecimal(0)
    if (number > 1000) {
      max = 999.99
    } else {
      max = number
    }
    max
  }

  /**
   * 判断字符串是否为指定格式日期
   *
   * @param str
   * @param format
   * @return
   */
  def isDate(str: String, format: String): Boolean = {
    if (str == null && str.isEmpty) {
      false
    } else {
      val dataFormat: SimpleDateFormat = new SimpleDateFormat(format)
      try {
        dataFormat.parse(str)
        true
      } catch {
        case _: Throwable =>
          false
      }
    }
  }

  /**
   * 获取今天是星期几
   * @return
   */
  def getDayOfWeek(dateTime: String) : Int = {
    // 获取今天日期
    val calendar = Calendar.getInstance()
    // 今天是一年中的第几周
    val pattern = "yyyy-MM-dd HH:mm:ss"
    val date = new SimpleDateFormat(pattern).parse(dateTime)
    calendar.setTime(date)
    val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)
    var MyDayOfWeek=0
    dayOfWeek match {
      case 2 => MyDayOfWeek=1   //星期一
      case 3 => MyDayOfWeek=2   //星期二
      case 4 => MyDayOfWeek=3   //星期三
      case 5 => MyDayOfWeek=4   //星期四
      case 6 => MyDayOfWeek=5   //星期五
      case 7 => MyDayOfWeek=6   //星期六
      case 1 => MyDayOfWeek=7   //星期天

    }
    println(MyDayOfWeek)
    MyDayOfWeek
  }

  def beforeHourTime(): String = {
    val ymdFormat = new SimpleDateFormat("yyyyMMddHH")
    val day: Calendar = Calendar.getInstance()
    day.add(Calendar.HOUR, -1)
    ymdFormat.format(day.getTime)
  }


  val x_PI = 3.14159265358979324 * 3000.0 / 180.0
  val PI = 3.14159265358979324
  val a = 6378245.0
  //克拉索夫斯基椭球参数长半轴a
  val ee = 0.00669342162296594323 //克拉索夫斯基椭球参数第一偏心率平方

  /**
   * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换 即谷歌、高德 转 百度
   *
   * @param lng 火星坐标系经度
   * @param lat 火星坐标系纬度
   * @return 百度坐标系经纬度
   */
  def gcj02tobd09(lng: Double, lat: Double): (Double, Double) = {
    val z: Double = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI)
    val theta: Double = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI)
    val bd_lng: Double = z * Math.cos(theta) + 0.0065
    val bd_lat: Double = z * Math.sin(theta) + 0.006
    (bd_lng, bd_lat)
  }

  /**
   * GCJ02(火星坐标系) 转换为 WGS84(地球坐标系)
   *
   * @param lng 火星坐标系经度
   * @param lat 火星坐标系纬度
   * @return 地球坐标系经纬度
   */
  def gcj02towgs84(lng: Double, lat: Double): (Double, Double) = {
    var dlat: Double = transformlat(lng - 105.0, lat - 35.0)
    var dlng: Double = transformlng(lng - 105.0, lat - 35.0)
    val radlat: Double = lat / 180.0 * PI
    var magic: Double = Math.sin(radlat)
    magic = 1 - ee * magic * magic
    val sqrtmagic: Double = Math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
    dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
    val mglat: Double = lat + dlat
    val mglng: Double = lng + dlng
    (lng * 2 - mglng, lat * 2 - mglat)
  }

  /**
   * WGS84(地球坐标系)转GCj02(火星坐标系)
   *
   * @param lng 地球坐标系经度
   * @param lat 地球坐标系纬度
   * @return 火星坐标系经纬度
   */
  def wgs84togcj02(lng: Double, lat: Double): (Double, Double) = {
    var dlat: Double = transformlat(lng - 105.0, lat - 35.0)
    var dlng: Double = transformlng(lng - 105.0, lat - 35.0)
    val radlat: Double = lat / 180.0 * PI
    var magic: Double = Math.sin(radlat)
    magic = 1 - ee * magic * magic
    val sqrtmagic: Double = Math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
    dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
    val mglat: Double = lat + dlat
    val mglng: Double = lng + dlng
    (mglng, mglat)
  }


  /**
   * GCJ02(火星坐标系) 转换为 WGS84(地球坐标系) 纬度转换
   *
   * @param lng
   * @param lat
   * @return
   */
  def transformlat(lng: Double, lat: Double): Double = {
    var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
    ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0
    ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0
    ret
  }

  /**
   * GCJ02(火星坐标系) 转换为 WGS84(地球坐标系) 纬度转换
   *
   * @param lng
   * @param lat
   * @return
   */
  def transformlng(lng: Double, lat: Double): Double = {
    var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
    ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0
    ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0
    ret
  }

  def parseInt(s: String, defaultData: Int): Int = try {
    s.toInt
  } catch {
    case _: Exception => defaultData
  }

  def parseInt(s: String): Option[Int] = try {
    Some(s.toInt)
  } catch {
    case _: Exception => None
  }

  def parseDouble(s: String, defaultData: Double): Double = try {
    s.toDouble
  } catch {
    case _: Exception => defaultData
  }

  def parseDouble(s: String): Option[Double] = try {
    Some(s.toDouble)
  } catch {
    case _: Exception => None
  }

  def parseLong(s: String, defaultData: Long): Long = try {
    s.toLong
  } catch {
    case _: Exception => defaultData
  }

  def parseLong(s: String): Option[Long] = try {
    Some(s.toLong)
  } catch {
    case _: Exception => None
  }

  def parseString(ts: Timestamp): Option[String] = try {
    Some(ts.toString)
  } catch {
    case _: Exception => None
  }

  def isIntByRegex(s : String) = {
    val pattern = """^(\d+)$""".r
    s match {
      case pattern(_*) => true
      case _ => false
    }
  }

  def main(args: Array[String]): Unit = {

  }
}
